using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

using Z.Linq;

namespace Furion.DatabaseAccessor
{
    public static partial class PagedQueryableExtensions
    {
        /// <summary>
        /// 分页扩展
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="entities"></param>
        /// <param name="pageIndex">索引</param>
        /// <param name="pageSize">条数</param>
        /// <returns></returns>
        public static PagedList<TEntity> ToPagedList<TEntity>(this IList<TEntity> entities, int pageIndex = 1, int pageSize = 20)
           where TEntity : new()
        {
            var totalCount = entities.Count();
            var items = entities.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
            var totalPages = (int)Math.Ceiling(totalCount / (double)pageSize);

            return new PagedList<TEntity>
            {
                PageIndex = pageIndex,
                PageSize = pageSize,
                Items = items,
                TotalCount = totalCount,
                TotalPages = totalPages,
                HasNextPages = pageIndex < totalPages,
                HasPrevPages = pageIndex - 1 > 0
            };
        }

        /// <summary>
        /// 分页扩展
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entities"></param>
        /// <param name="pageIndex">索引</param>
        /// <param name="pageSize">条数</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task<PagedList<TEntity>> ToPagedListAsync<TEntity>(this IList<TEntity> entities, int pageIndex = 1, int pageSize = 20, CancellationToken cancellationToken = default)
           where TEntity : new()
        {
            var totalCount = await entities.CountAsync(cancellationToken);
            var items = await entities.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync(cancellationToken);
            var totalPages = (int)Math.Ceiling(totalCount / (double)pageSize);

            return new PagedList<TEntity>
            {
                PageIndex = pageIndex,
                PageSize = pageSize,
                Items = items,
                TotalCount = totalCount,
                TotalPages = totalPages,
                HasNextPages = pageIndex < totalPages,
                HasPrevPages = pageIndex - 1 > 0
            };
        }

        /// <summary>
        /// 分页扩展(返回支持layui格式的数据)
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="entities"></param>
        /// <param name="pageIndex">查询页数</param>
        /// <param name="pageSize">条数</param>
        /// <returns></returns>
        public static PagedListToLayui<TEntity> ToPagedListToLayui<TEntity>(this IQueryable<TEntity> entities, int pageIndex = 1, int pageSize = 20)
        {
            var totalCount = entities.Count();
            var items = entities.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
            var totalPages = (int)Math.Ceiling(totalCount / (double)pageSize);

            return new PagedListToLayui<TEntity>
            {
                page = pageIndex,
                limit = pageSize,
                data = items,
                count = totalCount,
                totalpage = totalPages
            };
        }

        /// <summary>
        /// 分页扩展(返回支持layui格式的数据)
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="entities"></param>
        /// <param name="pageIndex">查询页数</param>
        /// <param name="pageSize">条数</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task<PagedListToLayui<TEntity>> ToPagedListToLayuiAsync<TEntity>(this IQueryable<TEntity> entities, int pageIndex = 1, int pageSize = 20, CancellationToken cancellationToken = default)
        {
            var totalCount = await entities.CountAsync(cancellationToken);
            var items = await entities.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync(cancellationToken);
            var totalPages = (int)Math.Ceiling(totalCount / (double)pageSize);

            return new PagedListToLayui<TEntity>
            {
                page = pageIndex,
                limit = pageSize,
                data = items,
                count = totalCount,
                totalpage = totalPages
            };
        }

        /// <summary>
        /// 分页扩展(返回支持layui格式的数据)
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="entities"></param>
        /// <param name="pageIndex">查询页数</param>
        /// <param name="pageSize">条数</param>
        /// <returns></returns>
        public static PagedListToLayui<TEntity> ToPagedListToLayui<TEntity>(this IList<TEntity> entities, int pageIndex = 1, int pageSize = 20)
        {
            var totalCount = entities.Count();
            var items = entities.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
            var totalPages = (int)Math.Ceiling(totalCount / (double)pageSize);

            return new PagedListToLayui<TEntity>
            {
                page = pageIndex,
                limit = pageSize,
                data = items,
                count = totalCount,
                totalpage = totalPages
            };
        }

        /// <summary>
        /// 分页扩展(返回支持layui格式的数据)
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="entities"></param>
        /// <param name="pageIndex">查询页数</param>
        /// <param name="pageSize">条数</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task<PagedListToLayui<TEntity>> ToPagedListToLayuiAsync<TEntity>(this IList<TEntity> entities, int pageIndex = 1, int pageSize = 20, CancellationToken cancellationToken = default)
        {
            var totalCount = await entities.CountAsync(cancellationToken);
            var items = await entities.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync(cancellationToken);
            var totalPages = (int)Math.Ceiling(totalCount / (double)pageSize);

            return new PagedListToLayui<TEntity>
            {
                page = pageIndex,
                limit = pageSize,
                data = items,
                count = totalCount,
                totalpage = totalPages
            };
        }
    }

    /// <summary>
    /// 数据集合(layui格式的数据)
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public class PagedListToLayui<TEntity>
    {
        public IEnumerable<TEntity> data { get; set; }

        /// <summary>
        /// 总数据条数
        /// </summary>
        public int count { get; set; }

        /// <summary>
        /// 状态码(默认为0)
        /// </summary>
        public int code { get; set; } = 0;

        /// <summary>
        /// 消息
        /// </summary>
        public string msg { get; set; } = "";

        /// <summary>
        /// 当前索引页
        /// </summary>
        public int page { get; set; }

        /// <summary>
        /// 每页显示条数
        /// </summary>
        public int limit { get; set; }

        /// <summary>
        /// 总页数
        /// </summary>
        public int totalpage { get; set; }
    }
}